import { ImportEntryOpts } from "import-html-entry";
import {
  registerMicroApps,
  start,
  runAfterFirstMounted,
  setDefaultMountApp,
  initGlobalState,
  prefetchApps,
  addGlobalUncaughtErrorHandler,
  loadMicroApp,
  LoadableApp,
  ObjectType,
  Patcher,
  PrefetchStrategy,
  AppMetadata,
  MicroAppStateActions,
  RegistrableApp,
} from "qiankun";
import { StartOpts } from "single-spa";

class MicroAppModule {
  constructor() {
    return this;
  }
  createRouter(props: RegistrableApp<ObjectType>[]) {
    registerMicroApps(props);
    return this;
  }
  createStore(
    app: { config: { globalProperties: { $actions: MicroAppStateActions } } },
    props: { state: {} }
  ) {
    let state = props.state || {};
    const actions = initGlobalState(state);
    actions.onGlobalStateChange((state, prev) => {
      console.log("[主应用][状态变化]", state, prev);
    });
    app.config.globalProperties.$actions = actions;
    return this;
  }
  setDefaultMountApp(props: string) {
    props && setDefaultMountApp(props); //设置主应用启动后默认进入的微应用
    return this;
  }
  prefetchApps(props: AppMetadata[]) {
    props && prefetchApps(props); //预加载微应用列表
    return this;
  }
  start(props: any) {
    start(props || {});
    runAfterFirstMounted(() => {
      console.log("[主应用][第一个微应用启动成功]");
    });
    return this;
  }
  startMicroApp(
    app: LoadableApp<ObjectType>,
    config:
      | ({
          $$cacheLifecycleByAppName?: boolean | undefined;
          prefetch?: PrefetchStrategy | undefined;
          sandbox?:
            | boolean
            | {
                strictStyleIsolation?: boolean | undefined;
                experimentalStyleIsolation?: boolean | undefined;
                loose?: boolean | undefined;
                speedy?: boolean | undefined;
                patchers?: Patcher[] | undefined;
              }
            | undefined;
          singular?:
            | boolean
            | ((app: LoadableApp<any>) => Promise<boolean>)
            | undefined;
          excludeAssetFilter?: ((url: string) => boolean) | undefined;
          globalContext?: (Window & typeof globalThis) | undefined;
        } & ImportEntryOpts &
          StartOpts & { autoStart?: boolean | undefined })
      | undefined
  ) {
    return loadMicroApp(app, config);
  }
}

class MicroApp {
  options: {
    install: Function;
  };
  constructor(props: { install: any }) {
    this.options = props;
    return this;
  }
  create() {
    const props = this.options;
    return new Promise((resolve, reject) => {
      try {
        if (props && props.install) {
          const microApp = new MicroAppModule();
          addGlobalUncaughtErrorHandler((err) => console.error(err));
          resolve((app: any) => {
            props.install(microApp, app, resolve);
          });
        } else {
          resolve(() => {});
        }
      } catch (err) {
        reject(err);
      }
    });
  }
}

export default MicroApp;
